package com.project.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.github.pagehelper.PageHelper;
import com.project.dao.UserDao;
import com.project.model.User;
import com.project.service.UserService;
import com.project.util.MyJWT;
import com.project.util.Util;
import org.apache.commons.codec.binary.Base64;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service(value = "UserService")
public class UserServiceImpl implements UserService {
    private String error;
    @Autowired
    private UserDao userDao;

    @Override
    public void setError(String error) {
        this.error = error;
    }

    @Override
    public String getError() {
        return error;
    }

    @Override
    public int addUser(User user) {
        User record = selectByEmail(user.getEmail());
        if (record != null) {
            this.setError("该邮箱已存在");
            return 0;
        }
        String password = user.getPassword();
        password = BCrypt.hashpw(password, BCrypt.gensalt());
        user.setPassword(password);
        return userDao.insertUser(user);
    }

    @Override
    public List<User> findAllUser(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);

        return userDao.selectAllUser();
    }

    @Override
    public User selectByEmail(String email) {
        return userDao.selectUserByEmail(email);
    }

    @Override
    public User selectByRememberToken(String rememberToken) {
        return userDao.selectUserByRememberToken(rememberToken);
    }

    @Override
    public User selectByPk(int id) {
        return userDao.selectUserByPrimaryKey(id);
    }

    @Override
    public Map getUserEditInfoByUser(User user) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", user.getId());
        map.put("nickname", user.getNickname());
        map.put("gender", user.getGender());
        map.put("githubName", user.getGithubName());
        map.put("email", user.getEmail());
        map.put("realName", user.getRealName());
        map.put("city", user.getCity());
        map.put("company", user.getCompany());
        map.put("weiboName", user.getWeiboName());
        map.put("weiboLink", user.getWeiboLink());
        map.put("personalWebsite", user.getPersonalWebsite());
        map.put("wechatQrcodeText", user.getWechatQrcodeText());
        map.put("paymentQrcodeText", user.getPaymentQrcodeText());
        map.put("introduction", user.getIntroduction());
        map.put("signature", user.getSignature());
        map.put("avatar", user.getAvatar());
        map.put("emailNotify", user.getEmailNotify());
        map.put("likeNotify", user.getLikeNotify());
        return map;
    }

    @Override
    public int setUserRememberToken(User user) {
        return userDao.updateUserByEmailSelective(user);
    }

    @Override
    public int updateUser(User user) {
        user.setUpdatedAt(Util.getFormatDate("yyyy-MM-dd HH:mm:ss"));
        return userDao.updateUserByPrimaryKeySelective(user);
    }

    @Override
    public Boolean isAdmin(User user) {
        String[] roles = null;
        String role = user.getRoles();
        if (role != null) {
            roles = role.split(",");
            if (Arrays.asList(roles).contains("ADMIN")) {
                return true;
            }
            return false;
        }
        return false;
    }

    @Override
    public Boolean hasLogin(HttpServletRequest request) {
        String accessToken = Util.getCookieValueByName(request, "accessToken");
        if (accessToken == null) {
            return false;
        }
        User user = getCurrentUser(request);
        if (user == null) {
            return false;
        }
        int id = getUserIdFromAccessToken(accessToken);
        String jwtSign = getCurrentJwtSignatureByPk(id);
        if (jwtSign == null) {
            return false;
        }
        return MyJWT.verifyJwt(accessToken, jwtSign);
    }

    @Override
    public User getCurrentUser(HttpServletRequest request) {
        String accessToken = Util.getCookieValueByName(request, "accessToken");
        if (accessToken == null) {
            return null;
        }
        DecodedJWT jwt = JWT.decode(accessToken);
        Base64 base64 = new Base64();
        String payload = new String(base64.decode(jwt.getPayload()));
        JSONObject payloadJson = JSON.parseObject(payload);
        User user = this.selectByPk(payloadJson.getIntValue("userid"));
        return user;
    }

    @Override
    public Integer getUserIdFromAccessToken(String token) {
        DecodedJWT jwt = JWT.decode(token);
        Base64 base64 = new Base64();
        String payload = new String(base64.decode(jwt.getPayload()));
        JSONObject payloadJson = JSON.parseObject(payload);
        return payloadJson.getIntValue("userid");
    }

    @Cacheable(cacheNames = "users", key = "#id")
    @Override
    public String getCurrentJwtSignatureByPk(int id) {
        User user = selectByPk(id);
        return user.getJwtSignature();
    }
    @CacheEvict(cacheNames = "users",key = "#id")
    @Override
    public int deleteJwtSignature(int id) {
        return userDao.deleteUserJwtSignature(id);
    }
}
